package com.lisa.auto.util;

import com.lisa.auto.entity.C3ReportCarInfo;
import net.sf.json.JSONObject;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;

/**
 * @author huangzhigang 2019/12/5
 */
public class DriveDirectionUtil {

    private static Logger logger = LoggerFactory.getLogger(DriveDirectionUtil.class);

    /**
     * 请求服务权限标识
     */
    static final String KEY = "c1a64dd269b2ba00372ee3c8ee54d963";
    /**
     * 获取经纬度请求URL
     */
    static final String GEO_URL = "https://restapi.amap.com/v3/place/text?key=%s&keywords=%s";
    /**
     * 获取货车路径规划请求URL
     */
    static final String DIRECTION_TRUCK_URL = "https://restapi.amap.com/v3/direction/driving?key=%s&origin=%s&destination=%s&strategy=%s";

    /**
     * 逆地理编码(根据经纬度转换成地区)
     */
    static final String DIRECTION_REGEO_URL = "https://restapi.amap.com/v3/geocode/regeo?key=%s&location=%s";

    /**
     * 驾车选择策略
     * 下方策略返回多条路径规划结果
     * 10，返回结果会躲避拥堵，路程较短，尽量缩短时间，与高德地图的默认策略也就是不进行任何勾选一致
     * 11，返回三个结果包含：时间最短；距离最短；躲避拥堵 （由于有更优秀的算法，建议用10代替）
     * 12，返回的结果考虑路况，尽量躲避拥堵而规划路径，与高德地图的“躲避拥堵”策略一致
     * 13，返回的结果不走高速，与高德地图“不走高速”策略一致
     * 14，返回的结果尽可能规划收费较低甚至免费的路径，与高德地图“避免收费”策略一致
     * 15，返回的结果考虑路况，尽量躲避拥堵而规划路径，并且不走高速，与高德地图的“躲避拥堵&不走高速”策略一致
     * 16，返回的结果尽量不走高速，并且尽量规划收费较低甚至免费的路径结果，与高德地图的“避免收费&不走高速”策略一致
     * 17，返回路径规划结果会尽量的躲避拥堵，并且规划收费较低甚至免费的路径结果，与高德地图的“躲避拥堵&避免收费”策略一致
     * 18，返回的结果尽量躲避拥堵，规划收费较低甚至免费的路径结果，并且尽量不走高速路，与高德地图的“避免拥堵&避免收费&不走高速”策略一致
     * 19，返回的结果会优先选择高速路，与高德地图的“高速优先”策略一致
     * 20，返回的结果会优先考虑高速路，并且会考虑路况躲避拥堵，与高德地图的“躲避拥堵&高速优先”策略一致
     * *********下方策略仅返回一条路径规划结果*********
     * 0，速度优先，不考虑当时路况，此路线不一定距离最短
     * 1，费用优先，不走收费路段，且耗时最少的路线
     * 2，距离优先，不考虑路况，仅走距离最短的路线，但是可能存在穿越小路/小区的情况
     * 3，速度优先，不走快速路，例如京通快速路（因为策略迭代，建议使用13）
     * 4，躲避拥堵，但是可能会存在绕路的情况，耗时可能较长
     * 5，多策略（同时使用速度优先、费用优先、距离优先三个策略计算路径）。
     * 其中必须说明，就算使用三个策略算路，会根据路况不固定的返回一~三条路径规划信息。
     * 6，速度优先，不走高速，但是不排除走其余收费路段
     * 7，费用优先，不走高速且避免所有收费路段
     * 8，躲避拥堵和收费，可能存在走高速的情况，并且考虑路
     */
    static Integer STRATEGY_ = 12;
    /**
     * 出发点
     */
    static String START_ADDR = "广东省深圳市宝安区前进一路269号";
    /**
     * 目的地
     */
    static String END_ADDR = "广东省深圳市南山区梦海大道桂湾五路交叉口";

    public static JSONObject getDirection() {
        try {
            /*拼接说明：请求地址，请求服务权限标识，出发点经纬度，目的地经纬度, 车辆大小*/
            String reqUrl = String.format(DIRECTION_TRUCK_URL, KEY, getLngLat(START_ADDR), getLngLat(END_ADDR), STRATEGY_);
            String result = getResponse(reqUrl);
            if (StringUtils.isBlank(result)) {
                return null;
            }
            JSONObject jsonObj = JSONObject.fromObject(result);
            if (!"10000".equals(jsonObj.getString("infocode"))) {
                logger.info("错误码 : {}, 访问地址查看错误码说明[https://lbs.amap.com/api/webservice/guide/tools/info/?sug_index=0]", jsonObj.getString("infocode"));
                return null;
            }
            JSONObject route = jsonObj.getJSONObject("route");
            route.put("originAddr", START_ADDR);
            route.put("destinationAddr", END_ADDR);
            jsonObj.put("route", route);
            return jsonObj;
        } catch (Exception e) {
            logger.info(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取经纬度
     *
     * @param addr 地址
     * @return 经纬度
     */
    static String getLngLat(String addr) {
        try {
            String url = String.format(GEO_URL, KEY, addr);
            String result = getResponse(url);
            if (StringUtils.isBlank(result)) {
                return null;
            }
            JSONObject jsonObj = JSONObject.fromObject(result);
            String resultCode = jsonObj.getString("infocode");
            if (!"10000".equals(resultCode)) {
                return null;
            }
            JSONObject jsonObject = JSONObject.fromObject(jsonObj.getJSONArray("pois").get(0));
            return jsonObject.getString("location");
        } catch (Exception e) {
            logger.info(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 获取经纬度获取地址
     *
     * @param
     * @return 地址
     */
    public static Map<String, String> transAddress(C3ReportCarInfo c3ReportCarInfo) {
        Map<String, String> map = new HashMap<>();
        try {
            BigDecimal latitude = c3ReportCarInfo.getLatitude().setScale(6,BigDecimal.ROUND_HALF_DOWN);
            BigDecimal longitude = c3ReportCarInfo.getLongitude().setScale(6,BigDecimal.ROUND_HALF_DOWN);
            String url = String.format(DIRECTION_REGEO_URL, KEY, longitude+","+latitude);
            String result = getResponse(url+"&radius=0&extensions=base&output=JSON");
            if (StringUtils.isBlank(result)) {
                return null;
            }
            JSONObject jsonObj = JSONObject.fromObject(result);
            String resultCode = jsonObj.getString("infocode");
            if (!"10000".equals(resultCode)) {
                return null;
            }
            JSONObject object = JSONObject.fromObject(jsonObj.get("regeocode"));
            if (object.containsKey("formatted_address")){
                map.put("detailedAddr", object.getString("formatted_address"));
            }
            JSONObject jsonObject = JSONObject.fromObject(object.get("addressComponent"));
            String province = jsonObject.getString("province");
            String city = jsonObject.getString("city");
            map.put("province", province);
            map.put("city", city);
            String district = jsonObject.get("district").toString();
            if ("[]".equals(district)) {
                map.put("district", jsonObject.getString("township"));
            } else {
                map.put("district", jsonObject.getString("district"));
            }
            if (StringUtils.isNotBlank(province) && province.endsWith("市")) {
                map.put("city", jsonObject.getString("直辖市"));
            }
            if (StringUtils.isNotBlank(province) && province.endsWith("省") && "[]".equals(city)) {
                map.put("city", jsonObject.getString("直辖县"));
            }
            return map;
        } catch (Exception e) {
            logger.info(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 通过URL请求
     *
     * @param reqUrl 请求地址
     * @return 返回信息
     */
    static String getResponse(String reqUrl) {
        StringBuffer result = new StringBuffer();
        try {
            URL url = new URL(reqUrl);
            URLConnection conn = url.openConnection();
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
            in.close();
            return result.toString();
        } catch (Exception e) {
            logger.info(e.getMessage(), e);
        }
        return null;
    }


}
